package com.ecelin.service;

import com.ecelin.entities.Column;
import com.ecelin.entities.KeyValue;
import com.ecelin.utils.AutoCloseableUtils;
import com.ecelin.utils.CustomException;
import com.ecelin.utils.StrUtils;

import javax.swing.filechooser.FileSystemView;
import java.io.File;
import java.sql.*;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.Properties;
import java.util.stream.Collectors;

/**
 * @author ecelin@ecelin.com
 */
public class InfoHandler {
	public static void collect(Properties pro, String tableName) throws Exception {
		Class.forName("com.mysql.cj.jdbc.Driver");
		KeyValue keyValue = checkProperty(pro, tableName);
		List<Column> list = jdbcHandler(keyValue);
		collocation(keyValue, list);

		//制作程序
		Generate.makeFile(keyValue);
	}

	private static void collocation(KeyValue keyValue, List<Column> list) {
		List<String> fieldList = list.stream().map(Column::getField).distinct().collect(Collectors.toList());
		StringBuilder fieldSb = new StringBuilder();
		for (int i = 0; i < fieldList.size(); i++) {
			fieldSb.append(fieldList.get(i));
			if (i < fieldList.size() - 1) {
				fieldSb.append(", ");
			}
			if ((i + 1) % 3 == 0 && i + 1 < fieldList.size()) {
				fieldSb.append("\r\n\t\t");
			}
		}
		keyValue.setBaseColumnList(fieldSb.toString());
		keyValue.setClassName(StrUtils.className(keyValue.getTableName(), keyValue.getIgnoredPrefix()));
		keyValue.setCamelClassName(keyValue.getClassName().substring(0, 1).toLowerCase() + keyValue.getClassName().substring(1));
		keyValue.setRestMappingClassName(StrUtils.camelName(keyValue.getTableName()));
		keyValue.setAuthor(System.getProperty("user.name"));
		keyValue.setBaseResultMap(list.stream().filter(vo -> vo.getXmlResultMap() != null).map(Column::getXmlResultMap)
				.distinct().collect(Collectors.joining("\r\n", "", "")));

		keyValue.setEntityImportClass(list.stream().filter(vo -> vo.getImportClass() != null).map(Column::getImportClass)
				.distinct().sorted(new StrUtils()).collect(Collectors.joining("\r\n")));

		File projectPath = new File(FileSystemView.getFileSystemView().getHomeDirectory(), keyValue.getProjectName());
		String locationPath = keyValue.getLocation().replace(".", "/");
		keyValue.setProjectPath(projectPath);
		keyValue.setMainClassPath(new File(projectPath, "src/main/java/" + locationPath));
		keyValue.setResourcesPath(new File(projectPath, "src/main/resources"));
		keyValue.setTestClassPath(new File(projectPath, "src/test/java/" + locationPath));
		list = list.stream().map(vo -> {
					String update = "update";
					String string = "String";
					String aLong = "Long";
					String integer = "Integer";
					String date = "Date";
					String localDate = "LocalDate";
					String localTime = "LocalTime";
					String field = vo.getCamelName().substring(0, 1).toUpperCase() + vo.getCamelName().substring(1);
					if (string.equals(vo.getJavaType())) {
						vo.setQuery(".like(StringUtils.isNotBlank(dto.get" + field + "()), " + keyValue.getClassName() + "::get" + field + ", dto.get" + field + "())");
					} else if (aLong.equals(vo.getJavaType()) || integer.equals(vo.getJavaType())) {
						vo.setQuery(".eq(dto.get" + field + "() != null, " + keyValue.getClassName() + "::get" + field + ", dto.get" + field + "())");
					}
					if (date.equals(vo.getJavaType()) || localDate.equals(vo.getJavaType()) || localTime.equals(vo.getJavaType())) {
						if (keyValue.getOrderBy() == null) {
							keyValue.setOrderBy(".orderByDesc(" + keyValue.getClassName() + "::get" + field + ")");
						} else {
							if (vo.getCamelName().toLowerCase().contains(update)) {
								keyValue.setOrderBy(".orderByDesc(" + keyValue.getClassName() + "::get" + field + ")");
							}
						}
					}
					return vo;
				}
		).collect(Collectors.toList());
		keyValue.setList(list);

		List<String> queries = keyValue.getList().stream().map(Column::getQuery).filter(Objects::nonNull).sorted(new StrUtils()).collect(Collectors.toList());
		StringBuilder stringBuilder = new StringBuilder("lambdaQueryWrapper");
		for (int i = 0; i < queries.size(); i++) {
			stringBuilder.append(queries.get(i));
			if (i != queries.size() - 1) {
				stringBuilder.append("\n\t\t\t\t");
			}
		}
		if (keyValue.getOrderBy() == null) {
			stringBuilder.append(";");
		} else {
			stringBuilder.append(keyValue.getOrderBy()).append(";");
		}
		keyValue.setLwq(stringBuilder.toString());
		String pri = "PRI";
		for (Column column : list) {
			if (column.getKey().contains(pri)) {
				keyValue.setIdType(column.getJavaType());
				break;
			}
		}
	}

	private static List<Column> jdbcHandler(KeyValue keyValue) throws Exception {
		List<Column> list = new ArrayList<>();
		Connection connection = null;
		PreparedStatement statement = null;
		ResultSet query = null;
		try {
			connection = DriverManager.getConnection(keyValue.getUrl(), keyValue.getUserName(), keyValue.getPassword());
			statement = connection.prepareStatement("show full fields from " + keyValue.getTableName());
			query = statement.executeQuery();
			while (query.next()) {
				Column columnInfo = new Column(query.getString("Field"),
						query.getString("Comment"),
						query.getString("Type"),
						"YES".equals(query.getString("Null")) ? null : "YES",
						query.getString("Key")
				);
				list.add(columnInfo);
			}
		} catch (SQLException e) {
			e.printStackTrace();
			throw new CustomException(e.getMessage());
		} finally {
			AutoCloseableUtils.close(query, statement, connection);
		}

		try {
			connection = DriverManager.getConnection(keyValue.getUrl(), keyValue.getUserName(), keyValue.getPassword());
			statement = connection.prepareStatement("show index from " + keyValue.getTableName());
			query = statement.executeQuery();
			while (query.next()) {
				for (int i = 0; i < list.size(); i++) {
					Column columnInfo = list.get(i);
					if (columnInfo.getField().equals(query.getString("Column_name"))) {
						columnInfo.setIsIndex("YES");
					}
				}
			}
		} catch (SQLException e) {
			e.printStackTrace();
			throw new CustomException(e.getMessage());
		} finally {
			AutoCloseableUtils.close(query, statement, connection);
		}

		try {
			connection = DriverManager.getConnection(keyValue.getUrl(), keyValue.getUserName(), keyValue.getPassword());
			statement = connection.prepareStatement("show create table " + keyValue.getTableName());
			query = statement.executeQuery();
			while (query.next()) {
				String queryString = query.getString("Create Table");
				String createSql = "-- # drop table if exists '" + keyValue.getTableName() + "';\r\n";
				createSql = createSql + "-- # --------------------------------------------------------\r\n";
				keyValue.setCreateSql(createSql + queryString);
				int a = queryString.lastIndexOf(")");
				int b = queryString.lastIndexOf("COMMENT=");
				if (a < b) {
					keyValue.setTableComment(queryString.substring(b + "COMMENT=".length()).replace("'", ""));
				} else {
					keyValue.setTableComment(keyValue.getTableName());
				}
			}
		} catch (SQLException e) {
			e.printStackTrace();
			throw new CustomException(e.getMessage());
		} finally {
			AutoCloseableUtils.close(query, statement, connection);
		}
		return list;
	}

	private static KeyValue checkProperty(Properties pro, String tableName) {
		KeyValue keyValue = new KeyValue();
		keyValue.setTableName(tableName);
		String password = pro.getProperty("password");
		if (StrUtils.isNull(password)) {
			throw new CustomException("password参数不能为空!");
		} else {
			keyValue.setPassword(password.trim());
		}

		String userName = pro.getProperty("userName");
		if (StrUtils.isNull(userName)) {
			throw new CustomException("userName参数不能为空!");
		} else {
			keyValue.setUserName(userName.trim());
		}

		String location = pro.getProperty("location");
		if (StrUtils.isNull(location)) {
			throw new CustomException("location参数不能为空!");
		} else {
			keyValue.setLocation(location.trim());
		}

		String projectName = pro.getProperty("projectName");
		if (StrUtils.isNull(projectName)) {
			throw new CustomException("projectName参数不能为空!");
		} else {
			keyValue.setProjectName(projectName.trim());
		}

		String ignoredPrefix = pro.getProperty("ignoredPrefix");
		if (StrUtils.isNull(ignoredPrefix)) {
			keyValue.setIgnoredPrefix(null);
		} else {
			keyValue.setIgnoredPrefix(ignoredPrefix.trim());
		}

		String ip = pro.getProperty("ip");
		if (StrUtils.isNull(ip)) {
			throw new CustomException("ip参数不能为空!");
		}

		String databaseName = pro.getProperty("databaseName");
		if (StrUtils.isNull(databaseName)) {
			throw new CustomException("databaseName参数不能为空!");
		}

		keyValue.setUrl("jdbc:mysql://" + ip.trim() + ":3306/" + databaseName.trim());
		String port = pro.getProperty("port");
		if (port == null || "".equals(port.trim())) {
			port = "8080";
		}
		keyValue.setPort(port);
		return keyValue;
	}
}
